package com.meshnetics.gb.type.impl.zcl;

import com.meshnetics.gb.type.DataTypeID;
import com.meshnetics.gb.type.DataValue;
import com.meshnetics.gb.type.MandatoryFormatter;

import java.nio.ByteBuffer;

/**
 * WRITE DESCRIPTION HERE
 *
 * @author AKovylin
 */
public final class TypeNull extends AbstractDataType {
    public static final String[] ALIASES = new String[]{
            "NULL", "Null", "null"
    };
    public static final TypeNull TYPE = new TypeNull();
    public static final Null VALUE = new Null(TYPE);

    public static final DataTypeID DATA_TYPE_ID = new DataTypeID((byte) 0x00, "Null", "No data");

    private final MandatoryFormatter formatter = new NullTypeMandatoryFormatter();

    private TypeNull() {
        super(ALIASES, DATA_TYPE_ID);
    }

    public DataValue valueOf(byte[] value) {
        if (value == null) {
            throw new NullPointerException("value is null");
        }
        if (value.length > 0) {
            throw new IllegalArgumentException("null value must have 0 octet length");
        }
        return VALUE;
    }

    public DataValue valueOf(String value) {
        if (value == null) {
            throw new NullPointerException("value is null");
        }
        if (value.length() > 0) {
            throw new IllegalArgumentException("null value must have 0 octet length");
        }
        return VALUE;
    }

    public DataValue fromObject(Object value) {
        if (value != null) {
            throw new IllegalArgumentException("not a null value");
        }
        return VALUE;
    }

    public DataValue deserialize(ByteBuffer bb) {
        if (bb == null) {
            throw new NullPointerException("bb is null");
        }
        return VALUE;
    }

    public MandatoryFormatter getMandatoryFormatter() {
        return formatter;
    }

    private final class NullTypeMandatoryFormatter extends MandatoryFormatter {
        public NullTypeMandatoryFormatter() {
            super(TypeNull.this);
        }

        public DataValue valueOf(String serializedValue) {
            return valueOf(serializedValue);
        }

        public String formatSerializedString(DataValue value) {
            checkValue(value);
            return "";
        }

        public String formatShortLogString(DataValue value) {
            checkValue(value);
            return ALIASES[0] + '(' + ALIASES[2] + ')';
        }

        public String formatMaxLogString(DataValue value) {
            checkValue(value);
            return "NullValue(valueTypeClass=" + getClass() + ",valueClass=" + VALUE.getClass() +
                    ",value=" + VALUE + ')';
        }

        private void checkValue(DataValue value) {
            if (value == null) {
                throw new NullPointerException("value is null");
            }
            if (VALUE != value) {
                throw new IllegalArgumentException("unsupported value type " + value.getType());
            }
        }
    }
}
